package de.g18.scavengerhunt.overlay;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;

/**
 * This class is used to create overlays that can contain, handle and draw it's own OverlayItems.
 */
public class GraphicOverlay extends ItemizedOverlay<OverlayItem> {

    /** Holds all OverlayItems **/
    protected List<OverlayItem>                  overlayItems = new ArrayList<OverlayItem>();

    /** Holds and maps Drawable and OverlayItems **/
    protected Map<Drawable, Map<String, Object>> drawableMap  = new HashMap<Drawable, Map<String, Object>>();

    /**
     * Creates a new GraphicOverlay with default drawable.
     * 
     * @param defaultDrawable
     */
    public GraphicOverlay(Drawable defaultDrawable) {
        super(boundCenterBottom(defaultDrawable));
    }

    /**
     * Get's an OverlayItem by its position.
     * 
     * @return OverlayItem
     */
    @Override
    protected OverlayItem createItem(int i) {
        return overlayItems.get(i);
    }

    /**
     * Get's the size of the list with OverlayItems.
     * 
     * @return int
     */
    @Override
    public int size() {
        return overlayItems.size();
    }

    /**
     * Adds a drawable to the GraphicOverlay and draws it at specified GeoPoint on the map.
     * 
     * @param drawable
     * @param geoPoint
     * @param title
     * @param snippet
     */
    public void addDrawable(Drawable drawable, GeoPoint geoPoint, String title, String snippet) {
        OverlayItem overlayItem = new OverlayItem(geoPoint, title, snippet);
        overlayItem.setMarker(boundCenterBottom(drawable));
        overlayItems.add(overlayItem);

        Map<String, Object> drawableParamMap = new HashMap<String, Object>();
        drawableParamMap.put("overlayItem", (OverlayItem) overlayItem);
        drawableMap.put(drawable, drawableParamMap);
        populate();
    }

    /**
     * Rotates a drawable and updates the OverlayItem mapped to it to see the result on the map.
     * 
     * @param drawable
     * @param angle
     */
    public void rotateDrawable(Drawable drawable, int angle) {
        Map<String, Object> drawableParamMap = getDrawableParams(drawable);

        Bitmap sourceBitmap = ((BitmapDrawable) drawable).getBitmap();
        Bitmap canvasBitmap = sourceBitmap.copy(Bitmap.Config.ARGB_8888, true);
        canvasBitmap.eraseColor(Color.TRANSPARENT);

        Canvas canvas = new Canvas(canvasBitmap);
        Matrix matrix = new Matrix();
        matrix.setRotate((float) angle, canvas.getWidth() / 2, canvas.getHeight() / 2);
        canvas.drawBitmap(sourceBitmap, matrix, new Paint());

        Drawable newDrawable = new BitmapDrawable(canvasBitmap);
        for (OverlayItem overlayItem : overlayItems) {
            if (overlayItem.equals((OverlayItem) drawableParamMap.get("overlayItem"))) {
                overlayItem.setMarker(boundCenterBottom(newDrawable));
                break;
            }
        }
        populate();
    }

    /**
     * Get's params specified for a drawable.
     * 
     * @param drawable
     * @return
     */
    protected Map<String, Object> getDrawableParams(Drawable drawable) {
        Map<String, Object> drawableParamMap = new HashMap<String, Object>();
        drawableParamMap = drawableMap.get(drawable);
        return drawableParamMap;
    }

    /**
     * Removes a drawable from the GraphicOverlay.
     * 
     * @param drawable
     */
    public void removeDrawable(Drawable drawable) {
        Map<String, Object> drawableParamMap = getDrawableParams(drawable);
        overlayItems.remove((OverlayItem) drawableParamMap.get("overlayItem"));
        drawableMap.remove(drawable);
        populate();
    }
}